const CFG = require('../config');
const FUN = require('../comm/func');
const rCache = require('../model/redis_cache');
const DB = require('../model/model_data');
const dbHelp = require('../comm/db-helper');
const timLib = require('../comm/time-lib');
const PMR = require('../utils/policyManger');
const dataCalc = require('../comm/data-calc');

module.exports = class jsonVar
{
  // 将数据库选项缓存到redis
  // policy 数据库policy信息
  // opts 数据库json信息
  // CacheCallback 执行存储的子函数
  static InitCache(policy, opts, CacheFunc)
  {
    let devConf = PMR.baseParam(policy);//即将缓存到redis的参数

    if( (parseInt(opts.fetch_period)==0) ||
        (parseInt(policy.record_limit)==0) )
    {
      console.error('wrong json-var policy',policy.id);
      return false;
    }

    // 数据库处理,没有就新建
    dbHelp.createTab(devConf.table, policy.uid);

    //json options参数
    devConf._user_level = policy._user_level;
    devConf.vars = opts.vars;
    devConf.calc = opts.calc;
    devConf.record_limit = policy.record_limit; // 数据库条数上限
    devConf.record_duration = 0; // 数据库周期上限
    devConf.hwid = policy.master;
    devConf.channel = opts.channel;
    CacheFunc(policy.id, policy.master, devConf); // 记录到缓存
  } // end InitCache

  // 处理json数据
  // topic = {project,devType,func,devId}
  // dConf即InitCache中的obj
  // dataBuf即mq消息内容，buf对象
  static async DataIn(topic, devConf, DataBuf)
  {
    if (topic.func != 'var') return; // topic过滤
    let devId = topic.devId.split('-');
    if (devId[0] != devConf.channel) return; // 通道过滤

    let jsonStr = DataBuf.toString().replace(/\x00/g,'');
    let varsObj = JSON.parse(jsonStr); // 收到的变量值
    let varAllow = devConf.vars.split(','); // 允许记录的
    let calc = devConf.calc.split(','); // 变量表达式
    if (calc[0] == null) calc[0] = '#v';

    if (devConf.table == 'dat_json') {
      let allowVarObj = {};
      for (let i in varAllow) {
        let vTag = varAllow[i].split(':'); // 分割替代名
        let vName = vTag[1] ? vTag[1] : vTag[0]; // 没有替代名就用原名
        vTag = vTag[0]; // 变量原名
        if (varsObj[vTag] == null) continue; // 无值
        if (calc[i] == null) calc[i] = calc[i-1]; // 算式往前默认
        allowVarObj[vName] = this.VarValueCalc(devConf, varsObj[vTag], calc[i].length?calc[i]:'#v');
      }
      this.Save2JsonTable(devConf, allowVarObj, varsObj._stamp ? varsObj._stamp : null); // 内置功能，保存时间戳变量为时间戳字段
    }

    //删除数据库中冗余的前期数据
    dataCalc.dbRecordTidy(devConf.uid,devConf.table,devConf.policy_id,devConf.record_limit);
  }

  // 通过算式计算变量值
  static VarValueCalc(dConf, value, calc)
  {
    let stamp = timLib.NowStamp();

    //进行算式计算
    if (calc) {
      calc = calc.replace(/#v/g, value);
      calc = calc.replace(/#t/g, parseInt(stamp/1000));
      try {
        value = eval(calc);
        return Number(value);
      } catch(err) {
        pcyLog('eval var calc string error! policy', dConf.policy_id);
        return -1;
      }
    }
  }

  // // 将变量存储到数据库
  // static async Save2VarTable(dConf, vtag, value, calc)
  // {
  //   let stamp = timLib.NowStamp();

  //   let db_stamp = await rCache.getKey(PMR.rdNode(dConf), 'db_stamp');
  //   if (db_stamp != null && stamp-db_stamp < CONFIG.DATA_SAVE_GAP) {pcyLog('[%d] jdata fast(%dmS)', dConf.hwid, stamp-db_stamp, stamp, db_stamp, timLib.NowStr()); return;} // 存储到数据库的频率不能过快

  //   //进行算式计算
  //   value = this.VarValueCalc(dConf, value, calc)

  //   //存数据
  //   DB.newRcd(dConf.uid, 'dat_var', 'hwid,policy_id,vtag,value,stamp',
  //             [dConf.hwid, dConf.policy_id, vtag, value, stamp]);
  //   rCache.setKey(PMR.rdNode(dConf), 'db_stamp', stamp, 60);//记录时间戳
  //   PMR.policyInform('update', dConf); // 通知前端
  // }

  // 将变量存储到数据库
  static async Save2JsonTable(dConf, varsObj, stamp = null)
  {
    if (stamp == null) stamp = timLib.NowStamp();

    let db_stamp = await rCache.getKey(PMR.rdNode(dConf), 'db_stamp');
    if (dConf._user_level == 0 && db_stamp != null) { // 普通用户存储到数据库的频率不能过快
      if (stamp-db_stamp < CFG.DATA_SAVE_GAP) {
        pcyLog(`[${dConf.hwid}][${dConf.policy}] json pkt too fast(${stamp-db_stamp}mS)`);
        return;
      }
    }

    //存数据
    DB.newRcd(dConf.uid, 'dat_json', 'hwid,policy_id,addr,json,stamp',
              [dConf.hwid, dConf.policy_id, dConf.channel, JSON.stringify(varsObj), stamp]);
    rCache.setKey(PMR.rdNode(dConf), 'db_stamp', stamp, 60);//记录时间戳
    PMR.policyInform('update', dConf); // 通知前端
  }



} //end class Modbus